package com.termux.project

import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Intent
import android.preference.PreferenceManager
import android.util.Log
import androidx.core.os.bundleOf
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.termux.R
import com.termux.backend.TerminalSession
import com.termux.frontend.config.NeoTermPath
import com.termux.frontend.floating.TerminalDialog
import com.termux.ui.ide.MainActivity
import com.termux.ui.term.NeoTermActivity
import com.termux.utils.PackageUtils
import org.apache.commons.io.FileUtils
import org.libsdl.app.SDLActivity
import java.io.File

class ProjectPresenter(var context: MainActivity) {

    private lateinit var project: Project
    private val PROJECT_KEY = "lastOrStoreProject_KEY"
    var configFile: File? = null
    fun openProject() {
        if (!this::project.isInitialized) {
            val projectFile =
                PreferenceManager.getDefaultSharedPreferences(context).getString(PROJECT_KEY, null)
            if (projectFile == null) {
                context.getViewBinding().fileView.setRootFile(
                    File(NeoTermPath.HOME_PATH),
                    null
                )
                return
            }
            configFile = File(projectFile)
            openProject(File(projectFile))
        }
    }

    fun updateProject() {
        if (this::project.isInitialized && configFile != null) {
            val config: JSONObject =
                JSON.parseObject(FileUtils.readFileToString(configFile, "utf-8"))
            project.execFilePath = config.getString("exec_file_path")
            project.type = config.getString("type")

        }

    }

    fun openProject(config: File?) {
        if (config != null) {
            if (!(config.canRead() || config.exists()))
                return
            configFile = config
        }
        val config: JSONObject = JSON.parseObject(FileUtils.readFileToString(configFile, "utf-8"))
        project = Project(
            config.getString("type"),
            configFile?.parent,
            config.getString("exec_file_path")
        )
        PreferenceManager.getDefaultSharedPreferences(context).edit()
            .putString(PROJECT_KEY, configFile?.absolutePath)
            .apply()
        initProjectUI()
    }

    private fun initProjectUI() {
        context.getViewBinding().fileView.setProjectFile(File(project.projectDir))
        initFileDesc(File(project.projectDir))
    }

    private fun initFileDesc(projectDir: File?) {
        with(context.getViewBinding().fileView) {
            this.putDesc(File(projectDir, "src"), "源文件")
            this.putDesc(File(projectDir, "include"), "头文件")
            this.putDesc(File(projectDir, "config.json"), "项目文件")
            this.putDesc(File(projectDir, "assets"), "资源文件")
            this.putDesc(File(projectDir, "CMakeLists.txt"), "CMake脚本")
            this.putDesc(File(projectDir, "build"), "编译目录")
        }
    }

    fun compileProject() {
        Log.d("idea", "compile project")
        val commands = "cd ${project.projectDir}\n" +
                "clear && mkdir -p build && cd build\n" +
                "cmake .. && make\n"
        val buildCommandFile = File("${NeoTermPath.USR_PATH}/tmp/buildCommands.sh\n")
        FileUtils.write(buildCommandFile, commands, "utf-8")
        TerminalDialog(context)
            .onFinish(object : TerminalDialog.SessionFinishedCallback {
                override fun onSessionFinished(
                    dialog: TerminalDialog,
                    finishedSession: TerminalSession?
                ) {
                    val exitState = finishedSession?.exitStatus ?: 1
                    if (exitState == 0) {
                        dialog.setTitle("编译成功！")
                    } else {
                        dialog.setTitle(context.getString(R.string.error))
                    }
                    FileUtils.forceDelete(buildCommandFile)
                }

            })
            .imeEnabled(true)
            .execute(
                "${NeoTermPath.USR_PATH}/bin/sh",
                arrayOf(
                    "${NeoTermPath.USR_PATH}/bin/sh",
                    buildCommandFile.absolutePath
                )
            )
            .show("编译中...")
    }

    fun runProject() {
        Log.d("idea", "run project")
        if (!this::project.isInitialized)
            return
        when (project.type) {
            "Console" -> startConsoleProgram()
            "NativeActivity" -> startNativeProgram()
            "SDL2" -> startSDLProgram()
        }
    }

    private fun startSDLProgram() {
        val intent = Intent()
        val componentName = ComponentName("com.termux.sdl", "org.libsdl.app.SDLActivity")
        intent.component = componentName
        project.copyFile()
        val bundle = bundleOf(
            "fname" to "${project.OUT_FILE}",
            "currdir" to project.projectDir
        )
        intent.putExtras(bundle)
        context.startActivity(intent)
    }

    private fun startNativeProgram() {
        val intent = Intent(context, IdeaNativeActivity::class.java)
        val bundle = bundleOf(
            "nativeApp" to "${project.projectDir}/${project.execFilePath}",
            "work_dir" to project.projectDir
        )
        intent.putExtras(bundle)
        context.startActivity(intent)
    }

    @SuppressLint("SdCardPath")
    fun getOpenDir(): String? {
        return if (this::project.isInitialized) {
            project.projectDir
        } else
            "/sdcard/IdeaProjects"
    }

    private fun startConsoleProgram() {
        val intent = Intent(context, NeoTermActivity::class.java)
        val bundle = bundleOf(
            "com.termux.console_program" to true,
            "work_dir" to project.projectDir,
            "run_commands" to "clear\n${project.OUT_FILE}\n"
        )
        project.copyFile()
        intent.putExtras(bundle)
        context.startActivity(intent)
    }
}